CI: redeploy ok-dspace on pushes to clarin-v7#175
Conversation
…branch
Sends a repository_dispatch to ufal/dspace-k8s once the images this environment
consumes have actually been pushed. That repository pins the tag to git and an
in-cluster reconciler applies it, so this job records a version and nothing
more - no deployment step and no cluster credential exists here, or anywhere in
GitHub.
Runs only for pushes to the default branch of the canonical repository, so a
pull request builds images but never triggers a deploy.
The token is a fine-grained PAT scoped to ufal/dspace-k8s with Contents: write,
which is what POST /repos/{owner}/{repo}/dispatches requires. A workflow's own
GITHUB_TOKEN cannot act on another repository, so this credential is
unavoidable; it is held as an organisation secret shared with this repository.
There was a problem hiding this comment.
Pull request overview
This PR updates the Docker image workflow to notify ufal/dspace-k8s (via repository_dispatch) after the ufal/dspace-angular dist image has been pushed on pushes to clarin-v7, enabling ok-dspace’s cluster-side reconciler to pick up and apply the new version.
Changes:
- Replaces the old commented-out deploy stub with a real
deploy-ok-dspacejob. - Gates the notification job to only run on pushes to
clarin-v7inufal/dspace-angularand only afterdspace-angular-distcompletes. - Triggers
ufal/dspace-k8sviapeter-evans/repository-dispatch@v4with a payload containing the frontend component and commit SHA.
The section header said "Redeploy" and the step was called "Trigger deployment", but this job only sends a repository_dispatch - the deploying happens in ufal/dspace-k8s and, ultimately, in the cluster. Renamed both so the workflow logs say what ran. Also names `clarin-v7` explicitly instead of "the default branch", since that is the literal value the guard matches and the two could drift apart.
The job authenticates with a fine-grained PAT and never uses GITHUB_TOKEN, but
inherited the workflow-level permissions anyway - including `packages: write` in
dspace-angular, which it has no use for. `permissions: {}` limits what a
compromised third-party action could reach from this job.
| permissions: {} | ||
| steps: | ||
| - name: Notify ufal/dspace-k8s | ||
| uses: peter-evans/repository-dispatch@v4 |
There was a problem hiding this comment.
don't use and action, hand roll it with curl (or gh cli if possible)
There was a problem hiding this comment.
Done — gh it is, since ubuntu-latest ships both gh (2.96.0) and jq (1.7.1), so no download is needed either.
- name: Notify ufal/dspace-k8s
env:
GH_TOKEN: ${{ secrets.OK_DSPACE_DEPLOY_TOKEN }}
SHA: ${{ github.sha }}
run: |
set -euo pipefail
jq -n --arg sha "${SHA}" \
'{event_type: "deploy-ok-dspace",
client_payload: {component: "frontend", sha: $sha}}' \
| gh api -X POST repos/ufal/dspace-k8s/dispatches --input -The payload is built by jq from an --arg rather than interpolated into a JSON string literal, so the value is a JSON string by construction instead of by careful quoting. Verified the emitted payload carries the same fields and values the action was sending, so nothing changes on the receiving end in pin-ok-dspace.yml. (Same JSON, not the same bytes — jq pretty-prints where the action sent compact; the API parses either.) gh api exits non-zero on an HTTP error, so a rejected dispatch still fails the job.
The real gain is that the PAT is no longer in the environment of third-party code for the sake of one POST. I also fixed the permissions: {} comment, which justified itself by "limits what a compromised third-party action could reach" — there is no longer one. Least privilege still applies, just for the plain reason that this job authenticates with the PAT and never touches GITHUB_TOKEN.
actionlint with shellcheck is clean.
peter-evans/repository-dispatch@v4 ran with the deploy PAT in its
environment to make a single POST. ubuntu-latest already ships gh and
jq, so the same call is three lines with no third-party code in the
credential's blast radius.
jq builds the payload from an --arg rather than interpolating the sha
into a JSON string, so the value is a JSON string by construction. The
request body is identical to what the action sent.
The permissions comment no longer justifies itself by third-party
actions, since there are none here now; permissions: {} still stands on
its own, because the job authenticates with the PAT and never touches
GITHUB_TOKEN.
Replaces the commented-out
deploy:stub with adeploy-ok-dspacejob that notifiesufal/dspace-k8sonce the image this test environment consumeshas been pushed. Target environment: https://ok-dspace.dyn.cloud.e-infra.cz.
The old stub targeted the dataquest docker-compose instances (
dev-5/dev-8) we no longer haveaccess to, which is why it was commented out rather than maintained.
This job records a version; it does not deploy. It sends a
repository_dispatch;dspace-k8spins the tag to git and a reconciler inside the cluster applies it. No deployment step and no cluster
credential exists in this repository — or anywhere in GitHub.
needs: [dspace-angular-dist], notdspace-angular— the latter builds the-devsuffixedimage, while the overlay runs the unsuffixed dist image. Easy to get backwards.
clarin-v7inufal/dspace-angular, so a pull request builds theimage but never triggers a deploy, and forks never fire it.
secrets.OK_DSPACE_DEPLOY_TOKENis a fine-grained PAT scoped toufal/dspace-k8swithContents: write, which is what
POST /repos/{owner}/{repo}/dispatchesrequires. It is alreadyconfigured as an organisation secret.
Worth knowing: the deploy verification on the other side reads this application's commit from
/static/VERSION_D, whichscripts/sourceversion.pygenerates at image build time — so that scriptstaying wired up in
docker.ymlis now load-bearing for confirming a deploy actually landed.Depends on ufal/dspace-k8s#39, which defines the
deploy-ok-dspacedispatch type. This PR isinert until that merges.